#include"Channel.hpp"
#include"Tasks.hpp"
#include<sys/types.h>
#include<sys/wait.h>

using work_t=std::function<void()>;

enum{
	ForkError=0,
	PipeError,
	Success,
	WaitError,
	UsageError
};

class ProcessPool{
public:
	ProcessPool(int num,work_t w):cnum(num),work(w){}

	int InitPool(){
		for(int i=0;i<cnum;i++){
			int fd[2]={0};
			int r=pipe(fd);
			if(r==-1)
				return PipeError;

			pid_t pid=fork();
			if(pid<0)
				return ForkError;
			else if(pid==0){
				std::cout<<"Close history wfd:";
				for(auto& x:channels){
				std::cout<<" "<<x.Name();
				x.Close();
				}
				std::cout<<"over"<<std::endl;

				::close(fd[1]);
				dup2(fd[0],0);
				work();
				exit(0);
			}

			::close(fd[0]);
			channels.emplace_back(pid,fd[1]);
			//std::cout<<"Emplace_back: "<<channels.back().Name()<<std::endl;
			sleep(1);
		}
		return Success;
	}

	void AssignTasks(){
		int cur=0;
		int TaskNum=20;
		while(TaskNum--){
			int SendNum=tasks.Select();
			std::cout<<"Send "<<SendNum<<" to "<<channels[cur].Name()<<std::endl;
			channels[cur++].SendMassage(SendNum);

			cur%=channels.size();
			sleep(1);
		}
	}

	int CleanPool(){
		for(auto& x: channels){
			std::cout<<"Close "<<x.Name()<<",";
			x.Close();

			pid_t rid=waitpid(x.Id(),nullptr,0);
			if(rid<=0)
				return WaitError;
			std::cout<<rid<<" was successfully waited for"<<std::endl;
		}

		return Success;
	}
	~ ProcessPool(){}
private:
	std::vector<Channel> channels;
	int cnum;
	work_t work;
};
